#coding:utf8
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from pynput import keyboard
from pynput import mouse
import sys
import redis
import json,time
import copy
f = open('config.json')
j = json.load(f)
f.close()
ip = j['ip']
port1 = j['port1']
port2 = j['port2']
sec = j['sec']
has_r_cmd = j['has_r_cmd']
menu_cmd_switch = j['menu_cmd_switch']
single_click = j['single_click']
is_type2 = j.get('is_type2',False)
insert_inner = j.get('insert_inner',True)
print('is_type2',is_type2)
right_click_gear = True
left_right_switch = j.get('left_right_switch',True)

replace_m = {"'5'#5#None":"<65437>#None#65437"}

force_switch = False
mm30auto = False #全屏定位自动消失
caps_kb_arr = True
multi_change = False
multi_change2 = True

add = ((ip,port1))
add2 = ((ip,port2))
redis_conn = redis.Redis(ip)
import threading
lock = threading.Lock()

input_key = True

mm = {}  #绝对定位，大范围
mm_scroll = {}
mm_scroll_pos_m = {}

abs_m = {} #微调

mm_key_to_indx = {} #绝对定位，精确
mm2 = {}#移动距离
mm3 = {}#点击配置
inner = {}    #放大框内部定位

#取图框整数倍移动
zytdx = {}
zytdy = {}

skip_keys = []

scroll_lock_mode = 0
pause_lock_mode = 0
print_lock_mode = 0
xing_mode = 0

print_m = {}
pause_m = {}
pause_m_limit = []
pause_m_limit2 = []

mm30pressed = False
mm30has = []
xing_m_big = {}
xing_m_small = {}
xing_m_times = {}
xing_m_arr = {"Key.left##":1, "Key.right##":2, "Key.up##":3, "Key.down##":4}
xing_last = ''

caps_on = True
add = ((ip,port1))
add2 = ((ip,port2))
connre = redis.Redis(ip)


is_pressed = False

def send(a,m=1):
    if m==2:
        ss = '%s#%s#xx'%(a)
    
    elif m==22:
        ss = '%s#%s#abs'%(a)
        
    elif m==23:
        ss = '%s#%s#abs3'%(a)

    elif m==24:
        ss = '%s#%s#abs'%(a)        
        
    elif m==3:
        ss = str(a)
        
    elif m==1:    
        if not is_pressed:
            i,j,pos = a
            ss = '%s#%s'%pos
        else:     
            ss = '4#a#a#a'
            for i in range(0,10):
                if '#%s#'%i in a:
                    ss = '%s#a#a#a'%i            
    elif m==4:
        ss = a
            
    try:
        with lock:
            redis_conn.rpush(str(port1),sec+ss)
            print(ss,time.time())
    except Exception as e:
        print(e)


def send2(ss):     
    try:
        with lock:
            redis_conn.rpush(str(port2),sec+ss)
    except Exception as e:
        print(e)

redis_conn.delete(str(port1))
redis_conn.delete(str(port2))
redis_conn.delete(str(port1)+'re')

g0=17
g1 = 1
g2 = 45    
cc = 0.75 

last_side = None
def send_sta():
    m = 1
    if last_side != None:
        m = 11
        
    elif mm30pressed:
        if len(mm30has)%2==0 and len(mm30has)>0:
            m = 3
        else:
            m = 2
    elif print_lock_mode>0:
        m = 4
    elif scroll_lock_mode>0:
        m = 5
    elif pause_lock_mode>0:        
        m = 6        
    elif xing_mode>0:        
        m = 7
        
    s = '%s'%m+'#'*13
    send(s,4)
  
def set_pause_m(j):
    global pause_m,pause_m_limit,pause_m_limit2
    pause_m = {}
    pause_m_limit = []
    pause_m_limit2 = ["Key.left##", "Key.right##", "Key.up##", "Key.down##"]
    
    
    l = j[13:27][::-1]+j[1:13]+j[27:41]
    pause_m_limit.append(l[0])
    pause_m_limit.append(l[-1])
    for i in range(40):
        dx = 200000
        dy = (i-19)*g0*cc
        if i>19:
            dy = (i-1-19)*g0*cc
        pause_m[l[i]] = (dx,dy)    
    
    pause_m["Key.up##"] = (pause_m[l[0]][0],pause_m[l[0]][1]*1.5)
    pause_m["Key.down##"] = (pause_m[l[-1]][0],pause_m[l[-1]][1]*1.5)
    #pause_m[l[0]] = pause_m[l[1]]    
    #pause_m[l[-1]] = pause_m[l[-2]]
    
    l = j[42:54]+j[66:74]+j[54:66]
    l2 = []
    for i in l:
        if not has_r_cmd and i=="Key.cmd_r##":
            continue
        l2.append(i)
    ll = len(l2)
    pause_m_limit.append(l2[0])
    pause_m_limit.append(l2[-1])

    for i in range(ll):                 
        dy = 200000
        dx = (i-ll//2)*g0
        pause_m[l2[i]] = (dx,dy)                    

    pause_m["Key.left##"] = (pause_m[l2[0]][0]*1.5,pause_m[l2[0]][1])
    pause_m["Key.right##"] = (pause_m[l2[-1]][0]*1.5,pause_m[l2[-1]][1])
        
    #pause_m[l2[0]] = pause_m[l2[1]]    
    #pause_m[l2[-1]] = pause_m[l2[-2]]

f = open('c.txt')
c0j = json.load(f)
if is_type2:
    tmp = []
    for i in c0j:
        if i =="'\\\\'#\\#92":
            tmp .append("Key.enter##")
        elif i == "Key.enter##":
            tmp.append("'\\\\'#\\#92")
        else:
            tmp.append(i)
    c0j = tmp                        
f.close()        

scroll_lock_abs_x = ''
scroll_lock_abs_y = ''

up_sign = ['']
down_sign = ['']
left_sign = ['']
right_sign = ['']
up_left_sign = ['']
up_right_sign = ['']
down_left_sign = ['']
down_right_sign = ['']

kb_arr = None
list1 = []
list2 = []
list3 = []
list4 = []
list1m = {}
list2m = {}
list3m = {}
list4m = {}
insert_inner_m = {}
mm_scroll_last_pos = (0,0)

def get_c0():
    global mm,inner,mm_key_to_indx,abs_m,print_m,mm_scroll
    global scroll_lock_abs_x,scroll_lock_abs_y
    global up_sign,down_sign,left_sign,right_sign,kb_arr,up_left_sign,up_right_sign,down_left_sign,down_right_sign
    global list1,list2,list3,list4,list1m,list2m,insert_inner_m,list3m,list4m
    insert_inner_m = {}
    list1 = []
    list2 = []
    list3 = []
    list4 = []
    list1m = {}
    list2m = {}    
    list3m = {}    
    list4m = {}    
    print_m = {}
    abs_m = {}
    mm_key_to_indx = {}
    mm = {}
    mm_scroll = {}
    inner = {}
    
    keys = []    
    try:                    
        j = c0j             
        set_pause_m(j)    
                    
        l = j[1:41]
        for i in range(40):
            dx = i/39
            print_m[l[i]] = (dx,-1)
            
        l = j[42:74]
        l2 = []
        for i in l:
            if not has_r_cmd and i=="Key.cmd_r##":
                continue
            l2.append(i)
        ll = len(l2)
        for i in range(ll):       
            dy = i/(ll-1)   
            print_m[l2[i]] = (-1,dy)
            
        l = j[1:13]      
        if insert_inner:
            l = j[54:66]
            l = j[1:13]      
        #l.reverse()
        abs_y = 1/4/12
        for i in range(12):
            dx = 0                        
            dy = abs_y*(i+1)            
            abs_m[l[i]] = (dx,dy)
                    
        l = []
        for i in (j[-7:-6]+j[-5:]):
            if not has_r_cmd and i=="Key.cmd_r##":
                continue            
            l.append(i)
        abs_x = 1/12/len(l)
        for i in range(len(l)):
            dy = 0                        
            dx = abs_x*(i+1)            
            abs_m[l[i]] = (dx,dy)                         
        
        
        xx = [j[54:66],j[41:54],j[27:41],j[13:27]]    
        xx.reverse()
        ax = 1/12/5
        ay = 1/4/12
        for i in range(4):
            jx = xx[i]
            
            for ii in range(len(jx)):
                if len(jx)==12:
                    insert_inner_m[jx[ii]] = (ax*(i+1),ay*(12-ii))
                else:
                    insert_inner_m[jx[ii]] = (ax*(i+1),ay*max(0.1,(12-ii)))
                
        co = 0
        for i in j:
            if i == 'Key.caps_lock##':
                continue
            s = i
            
            if menu_cmd_switch and s=="Key.menu##":
                continue
            
            if menu_cmd_switch and s=="Key.cmd_r##":
                s = "Key.menu##"
                        
            if not has_r_cmd and s=="Key.cmd_r##":
                continue
            if co>0:          
                mm_key_to_indx[s] = co
            else:
                mm_key_to_indx['sdfdsf'] = co

            co += 1
                    
        keys = [j[13:27],j[27:41],j[41:54],j[54:66]]    
        
        up_sign = ['s',"Key.up##"]
        down_sign = ['z',"Key.down##"]
        left_sign = ['a',"Key.left##"]
        right_sign = ['d',"Key.right##"]
        
        #up_left_sign = ['q']        
        #up_right_sign = ['e']        
        #down_left_sign =['z']        
        #down_right_sign = ['c']
        kb_arr = j[13:26]+j[28:40]+j[42:53]+j[55:65]+["Key.space##","'\\\\'#\\#92"]
        kb_arr += ["Key.tab##","Key.backspace##","Key.enter##"]
        kb_arr += ["Key.left##", "Key.right##", "Key.up##", "Key.down##","Key.cmd##"]
        
        for i in range(1,13):
            s = 'Key.f%s##'%i
            kb_arr.append(s)
        
        list1 = j[13:27]
        list2 = j[27:41]        
        list3 = [ "'h'#h#104", "'j'#j#106", "'k'#k#107", "'l'#l#108","';'#;#59", "\"'\"#'#39",]
        list4 = [ "'n'#n#110","'m'#m#109", "','#,#44", "'.'#.#46", "'/'#/#47", ]
        list1m = {}
        list2m = {}
        list3m = {}
        list4m = {}
        
        for i in range(len(list1)):
            list1m[list1[i]] = (i+1,len(list1)-i)
        
        for i in range(len(list2)):
            list2m[list2[i]] = (i+1,len(list2)-i)
            
        for i in range(len(list3)):
            list3m[list3[i]] = (i+1,len(list3)-i)
            
        for i in range(len(list4)):
            list4m[list4[i]] = (i+1,len(list4)-i)
        
        print(up_sign,down_sign,left_sign,right_sign,kb_arr)
        
        scroll_lock_abs_x =  {"Key.home##"'':(-1,-1),"Key.end##"'':(-1,1),
                              "Key.page_up##":(1,-1),"Key.page_down##":(1,1)}
        scroll_lock_abs_y = []#["Key.page_up##","Key.page_down##"]
        print('scroll_abs',scroll_lock_abs_x,scroll_lock_abs_y)
        
        xx = j[66:70]
        for i in range(4):
            inner[xx[i]] = (1/5*(i+1),1/3)
        xx = j[70:]
        for i in range(4):
            inner[xx[i]] = (1/5*(i+1),2/3)                        
         
        not_normal = {(0,12):(0,1),(0,13):(0,1),(1,12):(0,1),(1,13):(0,1),(2,12):(0,1)}
        key_size = []           
        for j in range(len(keys)):
            l = []
            for i in range(len(keys[j])):
                key_l = (1,1)
                if (j,i) in not_normal:
                    key_l = not_normal[(j,i)]
                l.append(key_l)
            key_size.append(l)    
                
        start_pos = [0,0]
        total_x = 0
        total_y = 0
        for i in key_size[0]:
            total_x += i[0]
        for i in key_size:        
            total_y += i[0][1]        
        
        for j in range(len(keys)):
            for i in range(len(keys[j])):
                size = key_size[j][i]
                posx = start_pos[0]
                posy = start_pos[1]
                if keys[j][i] != 'Key.caps_lock##':
                    mm[keys[j][i]] = (i,j,(posx,posy))                
                mm_scroll[keys[j][i]] = (i,j,(posx,posy))                
                mm_scroll_pos_m[(i,j)] = keys[j][i]                
                
                if i == len(keys[j])-1:
                    start_pos[0] = 0
                    start_pos[1] += size[1]/total_y
                else:
                    start_pos[0] += size[0]/total_x                            
    except Exception as e :
        print('get_c0 failed',e)   
        import traceback
        traceback.print_exception()
f = open('c2.txt')
c2j = json.load(f)
f.close()  

def get_c2():
    global mm2,zytdx,zytdy           
    mm2 = {}
    zytdx = {}
    zytdy = {}
    
    gap = [(-g2,0),(g2,0),(0,-g2),(0,g2),
           (-g1,0),(g1,0),(0,-g1),(0,g1),       
           (-g0,0),(g0,0),(0,-g0),(0,g0),(-g0,-g0),(-g0,g0),(g0,-g0),(g0,g0)
           ]      
    if force_switch:
        gap = [(-g2,0),(g2,0),(0,-g2),(0,g2),
               (-g1,0),(g1,0),(0,-g1),(0,g1),       
               (-g0,0),(g0,0),(-g0,0),(g0,0),
               (0,-g0),(0,g0),(0,-g0),(0,g0)
               ]      
        
    gap2 =[]
    for i in gap:
        j = (i[0],round(i[1]*cc))
        gap2.append(j)
    gap = gap2    
    
    try:                
        j = c2j        
        xx = j[len(gap):len(gap)+5]
        for i in range(5):
            zytdx[xx[i]] = i+1
        
        xx = j[len(gap)+5:len(gap)+17]
        for i in range(12):
            zytdy[xx[i]] = i+1
            
        for x in zip(j,gap):        
            mm2[x[0]] = x[1]                               
    except:
        print('get_c2 failed')

def get_c3():
    global mm3
    try:
        f = open('c3.txt')
        j = json.load(f)
        f.close()        
        j[0] = 'Key.pause##'
        for x in range(len(j)):        
            mm3[j[x]] = x    
    except:
        print('get_c3 failed')
            
def get_c4():
    try:
        global skip_keys
        f = open('c4.txt')
        skip_keys = json.load(f)
        f.close()    
        skip_keys[0] = 'Key.pause##'
        print('skip_keys',skip_keys)
    except:
        print('get_c4 failed')
        
def get_c567():
    try:        
        f = open('c5.txt')
        j = json.load(f)
        f.close()    
        co = 0
        for i in j:
            if not has_r_cmd and i=="Key.cmd_r##":
                continue
            if is_type2 and i=="'\\\\'#\\#92":
                continue
            xing_m_big[i] = co
            co += 1
        xing_m_big["Key.space##"] = 19
        f = open('c6.txt')
        j = json.load(f)
        f.close()    
        co = 0
        for i in j:            
            xing_m_small[i] = co
            co += 1
        f = open('c7.txt')
        j = json.load(f)
        f.close()    
        
        global xing_last
        xing_last = j[-1]
        co = 0
        for i in j:            
            xing_m_times[i] = co
            co += 1
            
        xing_m_times[j[-1]] = xing_m_times[j[-2]]
        xing_m_times["Key.home##"] = 0
        xing_m_times["Key.end##"] = 0
        
    except:
        print('get_c567 failed')

t = time.time()
get_c0()
get_c2()
print('get c0 c2',time.time()-t)

get_c3()
get_c4()
get_c567()

auto_gear=False
gear_on = False
def keyboard_socket_thr():
    global caps_on    
    while True:
        try:                         
            rr = str(port1)+'re'            
            xx = connre.blpop(rr)[1]            
            ss = xx.decode()                  
            if sec not in ss:
                continue
            ss = ss.replace(sec,'')
            global gear_on,auto_gear
            if ss=='auto_gear_on':
                auto_gear = True
                continue
            if ss=='auto_gear_off':
                auto_gear = False
                continue
            
            if ss=='gear_on':
                if not gear_on:
                    print('gear_on')
                gear_on = True
                continue
            if ss=='gear_off':
                if gear_on:
                    print('gear_off')
                gear_on = False
                continue 
            
            if ss=='1':
                caps_on = True
                continue
            if ss=='0':
                caps_on = False
                continue
            if ss=='2':
                global force_switch
                force_switch = not force_switch
                get_c0()
                get_c2()                      
                continue
            
            if ss =='3':
                global last_side,has_other_when_alt,has_other_when_ctrl
                last_side = None
                has_other_when_alt = True
                has_other_when_ctrl = True
                clear_all_mode()
                send_sta()
                continue
            
            l = ss.split('#')
            print(l)
            if len(l)==3:
                global g0,g2,cc
                g0=int(l[0])                
                g2 = int(l[1])    
                cc = float(l[2])
                get_c0()
                get_c2()      
                print('set g0')
        except Exception as e:
            print(e)
thr_k =  threading.Thread(target=keyboard_socket_thr)
thr_k.setDaemon(True)
thr_k.start()

codes = []
import time
def get_key_str(key):
    s = '%s'%key
    kc = ''
    kv = ''
    try:
        kc = key.char
    except:
        pass
    
    try:
        kv = key.vk
    except:
        pass
        
    return '%s#%s#%s'%(s,kc,kv)

import json

last_is_clear = False

def on_press2(key):            
    s = get_key_str(key)
    if not has_r_cmd and s=="Key.cmd_r##":
        return        
    if s =="'/'#/#None":
        if last_is_clear:
            send('#'*14,4)
        else:
            clear_all_mode()
            send_sta()
        return
        
    t = str(type(key))
    k = str(key)    
    if '\\x' in k:
        return    
    s = None
    if 'enum' in t:
        s = ('press','key',k.replace('Key.',''))
    if 'KeyCode' in t:
        if "'" == k[0]:
            kk = k.replace("'",'')
        else:
            kk = k.replace('"','')
        if kk=='\\\\':
            kk='\\'
        s = ('press','keycode',kk)        
    if s != None:
        send2(json.dumps(s))
        
def on_release2(key):
    s = get_key_str(key)
    print('on_release2',s)
    if s =="'/'#/#None":
        return
    if not has_r_cmd and s=="Key.cmd_r##":
        return        
    t = str(type(key))
    k = str(key)    
    if '\\x' in k:
        return    
    s = None
    if 'enum' in t:
        s = ('release','key',k.replace('Key.',''))
    if 'KeyCode' in t:
        if "'" == k[0]:
            kk = k.replace("'",'')
        else:
            kk = k.replace('"','')
        if kk=='\\\\':
            kk='\\'
        s = ('release','keycode',kk)                        
    if s != None:
        send2(json.dumps(s))
        
last_caps_time = 0
last_esc_time = 0


def deal_mm30():
    global mm30pressed,mm30has,print_lock_mode,pause_lock_mode,scroll_lock_mode
    print_lock_mode=pause_lock_mode=scroll_lock_mode=0
    if mm30pressed:
        if len(mm30has)==0:
            mm30has.append('xx')
        mm30has.append('xx')
        idx = 0
        ga = (idx-1)/(len(mm_key_to_indx)-2)        
        if len(mm30has)%2==1:
            ss = '%s#%s'%(ga,-1)
        else:
            ss = '%s#%s'%(-1,ga)
        send(ss, 4)
        print('send ',ss)       
    mm30pressed = True
    send_sta()    

def clear_all_mode():
    global scroll_lock_mode,pause_lock_mode,print_lock_mode,xing_mode
    global mm30pressed,mm30has
    scroll_lock_mode = pause_lock_mode = print_lock_mode = xing_mode = 0
    mm30pressed = False
    mm30has = []
def is_clear():
    if scroll_lock_mode==0 and pause_lock_mode==0 and print_lock_mode==0 and xing_mode==0 and (not mm30pressed):
        return True
    return False

num_lock_count = 0
last_m2 = ''
last_m2_2 = ''


last_arr = None
last_press_key = None

has_other_when_ctrl = False
has_other_when_alt = False
bk_pressed = False
last_pause_pressed = ''
xing_gap = 0


ding_pressed = -1
ding_has_other = False
ctrl_pressed = False
alt_pressed  = False
shift_pressed = False
insert_pressed = False
insert_inner_has = False
pause_pressed = False
print_pressed = False
pause_pressed_has_other = False
print_pressed_has_other = False

def on_press(key):         
    xx = str(key).replace('Key.','').replace("'",'')            
    global input_key, mm30pressed,mm30has,num_lock_count,xing_mode,last_pause_pressed
    global scroll_lock_mode,pause_lock_mode,print_lock_mode
    global last_m2,last_m2_2,last_side,last_arr,last_press_key,has_other_when_ctrl,has_other_when_alt
    global last_is_clear,xing_gap,ctrl_pressed,alt_pressed,shift_pressed
    global ding_pressed,ding_has_other,insert_pressed,pause_pressed,print_pressed
    global pause_pressed_has_other,print_pressed_has_other,insert_inner_has            
    last_is_clear = is_clear()    
    s = get_key_str(key)
    print('on_press',s)
    if s in replace_m:
        s = replace_m[s]
        print('replace_m',s)
    if s == 'Key.caps_lock##':                
        send('v2_caps_press',4)
        
    if insert_pressed and s == "Key.insert##":
        return            
    if pause_pressed and s == 'Key.pause##':
        return
    if print_pressed and s == "Key.print_screen##":
        return
    if pause_pressed and '65387' in s:
        return
    if pause_pressed:
        pause_pressed_has_other = True
    if print_pressed:
        print_pressed_has_other = True
        
    if s == 'Key.pause##':
        pause_pressed = True
        pause_pressed_has_other = False
        send('pauseini',4)
        
    if s == "Key.print_screen##":
        print_pressed_has_other = False
        print_pressed = True
        send('pauseini',4)
        
        
    if ding_pressed != -1:
        global ding_has_other
        ding_has_other = True
        ss = 'ding%s%s'%(ding_pressed,s)
        send(ss,4)
        return
    
    if s=='Key.caps_lock##' and caps_kb_arr and scroll_lock_mode == 0 and pause_lock_mode == 0 and print_lock_mode == 0 \
       and xing_mode == 0 and not mm30pressed:
        input_key = True
        if last_side == None:
            last_side = (g0,0)
        else:
            last_side = None
        send_sta()
        return
    
    if ctrl_pressed or shift_pressed or alt_pressed:
        print('csa pressed',ctrl_pressed , shift_pressed , alt_pressed)
        last_side = None
        send_sta()        
    
    if 'shift' in s:
        shift_pressed = True
        
    if 'ctrl' in s:        
        has_other_when_ctrl = False        
        ctrl_pressed = True
    else:
        has_other_when_ctrl = True
        
    if 'alt' in s:
        has_other_when_alt = False
        alt_pressed = True
    else:
        has_other_when_alt = True
        
    if s =="Key.print_screen##" and last_press_key=="Key.print_screen##":
        send(0,3)
    if s == "Key.insert##" and last_press_key=="Key.insert##" and scroll_lock_mode>0:
        send(7,3)
        
    last_press_key = s    
    
    if last_side != None and (not multi_change2 or s != "','#,#None"):                
        print('last_side_mode')
        if s not in kb_arr :
            print('not in kb_arr')
            if 'shift' not in s and 'ctrl' not in s and 'alt' not in s and \
               s not in ["'4'#4#None", "'6'#6#None","'7'#7#None", "'1'#1#None",
                         "'2'#2#None", "'8'#8#None","'9'#9#None", "'3'#3#None","'0'#0#None"]:                
                last_side = None
                send_sta()
        else:
            xx = s            
            if xx in list1m:
                ss = 'gap_move_list1%s#%s'%list1m[xx]
                send(ss,4)                    
                return
            
            if xx in list2m:
                ss = 'gap_move_list2%s#%s'%list2m[xx]
                send(ss,4)                    
                return
            
            if xx in list3m:
                ss = 'gap_move_list3%s#%s'%list3m[xx]
                send(ss,4)                    
                return
            
            if xx in list4m:
                ss = 'gap_move_list4%s#%s'%list4m[xx]
                send(ss,4)                    
                return
            
            for i in range(1,13):
                if 'Key.f%s##'%i in s:
                    ss = 'gap_move%s#'%i
                    send(ss,4)                    
                    return                                
            try:
                s2 = s.split('#')[0].replace("'",'')
            except:
                s2 = 'sdfsdf'
            if 'Key' in s:
                s2 = s
                
            if s2 in up_sign:
                last_side = (0,-g0)                
            elif s2 in down_sign:
                last_side = (0,g0)
                
            elif s2 in left_sign:
                last_side = (-g0,0)
            elif s2 in right_sign:
                last_side = (g0,0)
            elif s2 in up_left_sign:
                last_side = (-g0,-g0)
            elif s2 in up_right_sign:
                last_side = (g0,-g0)
            elif s2 in down_left_sign:
                last_side = (-g0,g0)
            elif s2 in down_right_sign:
                last_side = (g0,g0)
            if  s2 in['Key.enter##',"Key.cmd##"]:
                send(6,3)          
            #elif s2=='Key.enter##':
                #send(8,3)            
            else:                
                send(last_side,2)                
            return
        
    
    if last_m2 != last_m2_2:
        last_m2 = last_m2_2
    
    last_m2_2 = s
    
    if menu_cmd_switch and s=="Key.cmd_r##":
        s = "Key.menu##"
    if not has_r_cmd and s=="Key.cmd_r##":
        return
    
    if s=='Key.num_lock##':
        num_lock_count += 1
        if num_lock_count %2==0:
            send(1,3)
        return
    
    if mm3.get(s,-1) == 0:
        deal_mm30()
        send_sta()
        return
    
    if mm30pressed:
        if s == 'Key.caps_lock##':
            deal_mm30()
            send_sta()            
        elif (s not in mm_key_to_indx):
            print ('s not in mm_key_to_indx')
            mm30pressed = False
            mm30has = []
        else:
            if not pause_pressed:
                issame = False
                if len(mm30has)>0 and mm30has[-1]==s:
                    issame = True
                if len(mm30has)>0 and mm30has[-1]!=s:
                    mm30has.append(s)
                mm30has.append(s)
                idx = mm_key_to_indx[s]
                if issame:
                    idx = -1
                    mm30has[-1] = 'eiruuyw'
            else:
                mm30has.append(s)
                idx = mm_key_to_indx[s]
                
            ga = (idx-1)/(len(mm_key_to_indx)-2)        
            if len(mm30has)%2==1:
                ss = '%s#%s'%(ga,-1)
            else:
                ss = '%s#%s'%(-1,ga)
            send(ss, 4)
            print('send ',ss)       
            send_sta()
            return
        send_sta()
    
    if s == 'Key.caps_lock##' and xing_mode == 0 and scroll_lock_mode==0:
        if not caps_on:
            input_key = True
            send('caps_press',4)
        elif caps_kb_arr:
            input_key = True
        else:        
            print_lock_mode=pause_lock_mode=scroll_lock_mode=0
            send_sta()
            global last_caps_time            
            if time.time()-last_caps_time<0.3:                
                last_caps_time = time.time()
                return
            
            input_key = not input_key
            last_caps_time = time.time()
            print('change',input_key)
            return
        
    if input_key:
        if s in ("Key.insert##","Key.scroll_lock##","Key.print_screen##","'*'#*#None"):
            send('#'*12,4)
        
        if  xing_mode==0:
            if s =="'*'#*#None":
                xing_gap = 0
                clear_all_mode()
                xing_mode = 2                
                s = 'xing#1,%s,%s,%s,%s'%(g0,len(xing_m_big)-1,len(xing_m_small),len(xing_m_times))
                send(s,4)
                send_sta()
                return
            
        elif xing_mode>0:
            if s in xing_m_big:
                s = 'xing#2,%s'%xing_m_big[s]
                send(s,4)
                send('rawkey1'+str(key),4)
                return
            if s in xing_m_small:
                s = 'xing#3,%s'%xing_m_small[s]
                send(s,4)
                return
            if s in xing_m_arr:
                s = 'xing#6,%s'%xing_m_arr[s]
                send(s,4)
                return
            
            if s in xing_m_times:
                send('rawkey2'+str(key),4)                
                if s == "Key.home##":
                    xing_gap = max(xing_gap -19,0)                    
                if s == "Key.end##":
                    xing_gap += 19
                if s == xing_last:
                    xing_gap = 0
                if xing_gap==0 and s == "Key.home##":
                    ss = 'xing#4,%s'%(10+xing_gap)
                else:
                    ss = 'xing#4,%s'%(xing_m_times[s]+xing_gap)
                send(ss,4)
                if s == xing_last:
                    s = 'xing#5,%s,%s,%s,%s'%(g0,len(xing_m_big)-1,len(xing_m_small),len(xing_m_times))
                    send(s,4)                                
                return
            
                
            if s =="'*'#*#None":
                xing_gap = 0
                s = 'xing#1,%s,%s,%s,%s'%(g0,len(xing_m_big)-1,len(xing_m_small),len(xing_m_times))
                send(s,4)                                                
                return
            
        global mm_scroll_last_pos
        if  scroll_lock_mode==0:
            if s =="Key.insert##":
                insert_pressed = True
                insert_inner_has = False
                clear_all_mode()
                scroll_lock_mode = 2             
                ss = '%s#%s#sc_ini'%(0,0)
                send(ss,4)                
                return
        
        elif scroll_lock_mode>0:                        
            if s  in scroll_lock_abs_x:
                ss = '%s#%s#sc_xy_abs'%scroll_lock_abs_x[s]
                send(ss,4)
                return
            
            if s in scroll_lock_abs_y:
                ss = '%s#%s#sc_y'%(0,0)
                send(ss,4)
                return
            
            if s in ["Key.left##", "Key.right##", "Key.up##", "Key.down##"]:
                i,j = mm_scroll_last_pos
                print('mm_scroll_last_pos',i,j)
                if s=="Key.left##":
                    i -= 1
                if s=="Key.right##":
                    i += 1
                if s== "Key.up##":
                    j -=1
                if s=="Key.down##":
                    j += 1
                print(i,j)
                if (i,j) in mm_scroll_pos_m:
                    k = mm_scroll_pos_m[(i,j)]
                    i,j,pos = mm_scroll[k]
                    ss = '%s#%s#sc_start'%pos
                    send(ss,4)                
                    ss = '%s#%s#sc_xy'%(0,0)
                    send(ss,4)                 
                    insert_inner_has = True
                    mm_scroll_last_pos = (i,j)                                    
                return
            if s in mm_scroll and (not insert_inner_has or insert_pressed):
                i,j,pos = mm_scroll[s]
                ss = '%s#%s#sc_start'%pos
                send(ss,4)                
                ss = '%s#%s#sc_xy'%(0,0)
                send(ss,4)                 
                insert_inner_has = True
                mm_scroll_last_pos = (i,j)
                return                         
            
            if s in abs_m:                
                ss = '%s#%s#sc_xy'%abs_m[s]
                send(ss,4)
                return
            
            if insert_inner and not insert_pressed and insert_inner_has and s in insert_inner_m:                    
                ss = '%s#%s#sc_xy'%insert_inner_m[s]
                send(ss,4)
                return
            
            if s in mm_scroll:     
                i,j,pos = mm_scroll[s]
                ss = '%s#%s#sc_start'%pos
                send(ss,4)                
                ss = '%s#%s#sc_xy'%(0,0)
                send(ss,4)                 
                insert_inner_has = True
                mm_scroll_last_pos = (i,j)
                return                        
            
            if s =="Key.insert##":
                return
        
        if  pause_lock_mode==0:
            if s =="Key.scroll_lock##":
                clear_all_mode()
                pause_lock_mode = 2                
                send('#'*11,4)        
                last_pause_pressed = ''                
                send_sta()
                return
            
        elif pause_lock_mode>0:
            if s in pause_m:
                send(pause_m[s],23)                
                if s in pause_m_limit2:
                    send('#'*11,4)                               
                    
                if s in pause_m_limit and s == last_pause_pressed:
                    send('#'*11,4)                               
                    last_pause_pressed = ''
                else:
                    last_pause_pressed = s
                return
            
            if s =="Key.scroll_lock##":    
                send('#'*11,4)               
                last_pause_pressed = ''
                return
            
        if  print_lock_mode==0:
            if s =="Key.print_screen##":
                clear_all_mode()
                print_lock_mode = 2                
                send_sta()
                return
            
        elif print_lock_mode>0:
            if s in print_m:
                ss = '%s#%s'%print_m[s]
                send(ss,4)                
                return
            
            if s =="Key.print_screen##":
                return

    if (s not in skip_keys) and input_key:
        return on_press2(key)    
    if s=='Key.esc##':
        global is_pressed,last_esc_time
        last_esc_time = time.time()
        is_pressed = True
        print('is_pressed',is_pressed)
    
    if s in mm:                  
        print(mm[s])
        if not is_pressed:
            send(mm[s])        
        else:
            send(s)
    
    elif s in mm2:        
        print('send2',mm2[s])                    
        if s in ["'4'#4#None", "'6'#6#None","'7'#7#None", "'1'#1#None"] or last_arr==None or not force_switch:            
            last_arr = mm2[s]
        need_send_sta = False
        if last_side == None:
            need_send_sta = True
        last_side = last_arr
        if need_send_sta:
            send_sta()
        if force_switch and single_click:    
            last_m2_2 = last_m2
            if s != last_m2:
                last_m2 = s
                last_m2_2 = s
                send(last_arr,2)                
        else:
            send(last_arr,2)
            
    elif s in mm3:
        if mm3[s]!=0:
            print('send3',mm3[s])
            if s in ["'-'#-#None", "'+'#+#None","<65437>#None#65437"]:                
                ding_pressed = mm3[s]
                ding_has_other =False
            else:
                send(mm3[s],3)            
                global bk_pressed
                if s=="'0'#0#None" and multi_change2:
                    bk_pressed = True
                    
                if s=="','#,#None" and multi_change2:
                    if bk_pressed:
                        bk_pressed = False
                        last_side = None                                    
                    else:
                        if last_side==None:
                            last_side = (g0,0)
                        else:
                            last_side = None
                    send_sta()
                
    elif s in zytdx:
        if not is_pressed:
            ss = 'zytdx%s#'%zytdx[s]
        else:
            ss = 'zyt-dx%s#'%zytdx[s]
        send(ss,4)
    elif s in zytdy:
        if not is_pressed:
            ss = 'zytdy%s#'%zytdy[s]
        else:
            ss = 'zyt-dy%s#'%zytdy[s]
        send(ss,4)  
    elif s in inner:
        ss = '%sinner%s'%inner[s]
        send(ss,4)  
        
def on_release(key):
    global mm30pressed,mm30has
    global scroll_lock_mode,pause_lock_mode,print_lock_mode,xing_mode
    global shift_pressed,alt_pressed,ctrl_pressed
    global pause_pressed,print_pressed    
    s = get_key_str(key)
    print('on_release',s)
    if s in replace_m:
        s = replace_m[s]
        print('replace_m',s)
        
    if s == 'Key.caps_lock##':                
        send('v2_caps_release',4)
        
    if pause_pressed and '65387' in s:
        print('return 1')
        return
    
    if s=="Key.insert##":
        global insert_pressed
        insert_pressed = False
        
    if s == 'Key.pause##':
        pause_pressed = False        
        if not pause_pressed_has_other:
            send('pauseover',4)
        
    if s == "Key.print_screen##":
        print_pressed = False
        if not print_pressed_has_other:
            send('pauseover',4)
                
    if s in ["'-'#-#None", "'+'#+#None","<65437>#None#65437"]:
        global ding_pressed
        ding_pressed = -1
        if not ding_has_other:
            send(mm3[s],3)      
    if 'shift' in s:
        shift_pressed = False
        
    if 'ctrl' in s:        
        ctrl_pressed = False
        
    if 'alt' in s:
        alt_pressed = False    
        
    if ding_pressed != -1 and 'ctrl' not in s and 'alt' not in s and 'shift' not in s:
        print('return 2')
        return
    
    if s=='Key.caps_lock##' and caps_kb_arr and scroll_lock_mode == 0 and pause_lock_mode == 0 and print_lock_mode == 0 \
       and xing_mode == 0 and not mm30pressed:        
        send_sta()
        print('return 3')
        return
            
    
    if (('ctrl' in s and not has_other_when_ctrl) or ('alt' in s and not has_other_when_alt)) and multi_change :
        in_mode = False
        if mm30pressed or print_lock_mode>0 or scroll_lock_mode>0 or  pause_lock_mode>0 or xing_mode>0:      
            in_mode = True
        global last_side
        if last_side == None and not in_mode:
            last_side = (g0,0)
            send_sta()
    
    if last_side != None and s in kb_arr:
        print('release hit kb_arr')
        print('return 4')
        return                
    
    if menu_cmd_switch and s=="Key.cmd_r##":
        s = "Key.menu##"    
    if not has_r_cmd and s=="Key.cmd_r##":
        print('return 5')
        return    
    if s=='Key.num_lock##':
        print('return 6')
        return
    
    if mm30pressed and mm30auto:
        if len(mm30has)>=2:
            mm30pressed = False
            mm30has = []   
        send_sta()
        print('return 7')
        return
    if mm30pressed and not mm30auto:
        print('return 8')
        return
    
    if mm3.get(s,-1) == 0:
        print('return 9')
        return          
                
    if s == 'Key.caps_lock##' and xing_mode==0 and scroll_lock_mode==0:
        if not caps_on:            
            send('caps_release',4)                
    
    if input_key and xing_mode>0:
        if s == "'*'#*#None":
            xing_mode = 1        
        if s in xing_m_big or s in xing_m_small or s in xing_m_arr or s in xing_m_times or s == "'*'#*#None":
            print('return 10')
            return        
        xing_mode -= 1
        send_sta()            
        
    if input_key and scroll_lock_mode>0:        
        if s in mm_scroll or s in abs_m or s in ["Key.left##", "Key.right##", "Key.up##", "Key.down##"] \
           or s in insert_inner_m or s in scroll_lock_abs_x or s in scroll_lock_abs_y:
            print('return 11')
            return              
        
        scroll_lock_mode -= 1               
        send_sta()
        if s == "Key.insert##":
            print('return 12')
            return                  
        
    if input_key and pause_lock_mode>0:        
        if s == "Key.scroll_lock##":
            pause_lock_mode = 1
            print('return 13')
            return             
        
        if s in pause_m :
            print('return 14')
            return
        
        pause_lock_mode -= 1
        send_sta()        
        
        
    if input_key and print_lock_mode>0:        
        if s in print_m:
            print('return 15')
            return              
        
        print_lock_mode -= 1        
        print('print_lock_mode release ',print_lock_mode)
        send_sta()
        
        if s == "Key.print_screen##":
            print('return 16')
            return     
            
    if (s not in skip_keys) and input_key:
        return on_release2(key)
    
    if s=='Key.esc##':
        global is_pressed
        is_pressed = False
        print('esc last',time.time()-last_esc_time)
        if time.time()-last_esc_time<0.15:
            send(11,3)            
        print('is_pressed',is_pressed)
        
listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release,
)
listener.start()

last_xy = None
last_move_send_time = 0
last_move_send_time2 = 0
total_x = 0
total_y = 0
add_x = True
pass_scroll = False

min_gap = 0.05

def on_scroll(x, y, dx, dy):
    global last_move_send_time,total_x,total_y
    print(x,y,dx,dy,time.time())
    if pass_scroll:
        s = '%s#%s'%(dx,dy)+'#'*7
        send(s,4)            
        return
    
    if add_x:
        total_x += dy
    else:
        total_y += dy
    if time.time()-last_move_send_time<min_gap:
        return
    s = '%s#%s'%(-total_x,-total_y)+'#'*5
    total_y = total_x=0
    last_move_send_time = time.time()
    send(s,4)
    
total_x2 = 0
total_y2 = 0


last_right_click_time = 0

right_press_time = 0

def on_click_2(x, y, button, pressed):
    if not pressed:
        return
    if 'midd' in str(button):
        send('#'*27,4)

    if 'right' not in str(button):
        if left_right_switch:
            send('#'*28,4)  
        else:
            send('#'*7,4)
        return    
    if left_right_switch:
        send('#'*7,4)
    else:        
        send('#'*28,4)  
    global pass_scroll,add_x
    pass_scroll = True
    add_x = not add_x    
    

def on_click(x, y, button, pressed):
    print(x, y, button, pressed)
    print(str(button))
    if right_click_gear:
        return on_click_2(x, y, button, pressed)
    
    global last_right_click_time,pass_scroll,add_x,right_press_time        
    if pressed:
        if 'midd' in str(button):
            send('#'*27,4)
            return        
        if 'right' not in str(button):
            send('#'*7,4)
            return    
        send('#'*9,4)        
        right_press_time = time.time()
        return
    send('#'*10,4)            
    if time.time()-right_press_time>0.3:
        return
    
    if time.time()- last_right_click_time<0.3:
        pass_scroll = True
        add_x = not add_x
        return
    
    last_right_click_time = time.time()
    if pass_scroll  :
        pass_scroll = False
        add_x = True
        return    
    add_x = not add_x
    


move_pos = [-1,-1]

def on_move(dx,dy):    
    global last_xy,last_move_send_time2,total_x2,total_y2,add_x,move_pos
    add_x = True
    ss = 'on_move%s#%s'%(dx,dy)
    if auto_gear:
        send(ss,4)
    if time.time()-last_move_send_time2<min_gap and not gear_on:
        total_x2 += dx
        total_y2 += dy                
        return
    
    ax = total_x2 +dx
    ay = total_y2 +dy            
    last_move_send_time2 = time.time()
    s = '%s#%s'%(ax,ay)+'####'
    if ax != 0 or ay !=0 :
        send(s,4)
    total_x2=total_y2=0

def back_thr():
    global last_move_send_time,last_move_send_time2,total_x,total_y,total_x2,total_y2
    while True:
        time.sleep(0.005)                  
        if time.time()-last_move_send_time<min_gap:                    
            if total_y !=0 or total_x!=0:
                s = '%s#%s'%(-total_x,-total_y)+'#####'
                total_y = total_x=0
                last_move_send_time2 = time.time()
                send(s,4)
        if time.time()-last_move_send_time2<min_gap:                    
            if total_x2!=0 or total_y2!=0:
                last_move_send_time2 = time.time()
                s = '%s#%s'%(total_x2,total_y2)+'####'
                send(s,4)
                total_x2=total_y2=0
            
import threading
t = threading.Thread(target=back_thr)
t.setDaemon(True)
t.start()
def on_move_t_fun():
    import struct
    with open("/dev/input/mice", mode="rb") as f:
        while True:
            button, x, y = struct.unpack('Bbb', f.read(3))
            on_move(x,-y)
        
on_move_t = threading.Thread(target=on_move_t_fun)
on_move_t.setDaemon(True)
on_move_t.start()

mouse_listener = mouse.Listener(    
        on_click=on_click,    
on_scroll=on_scroll)
mouse_listener.start()
class my(QMainWindow):
    def __init__(self):
        super().__init__()         
        self.show()       
a = QApplication([])   
w = my()
a.exec_()
